#include<iostream>
#include<WinSock2.h>
#include<string>
#include <time.h>
#include<fstream>
#pragma warning(disable:4996)
#pragma comment (lib, "ws2_32.lib")  //加载 ws2_32.dll
using namespace std;

const int MAXBUF = 1024;
const double TIMEOUT = 0.5 * CLOCKS_PER_SEC;
#define SYN 4
#define ACK 2
#define FIN 1
#define ACK_SYN 6
#define ACK_FIN 3

struct HEADER {
	u_short len = 8;//2
	u_short ck_sum = 0;//2
	u_short flag = 0;//[SYN ACK FIN]	//2
	unsigned char seq_num = 0;//1
	unsigned char ack_num = 0;//1
}head;

u_short cksum(u_short* mes, int count) {//u_short宏定义为short类型，占2个字节；以16位为单位取报文(mes) 
	//mes指向报文，count表示报文-16位 为单位的组数
	u_long sum = 0;
	while (count--) {
		sum += *mes++;//以16位为单位累加
		if (sum & 0xffff0000) {//如果超出了两个字节，说明有溢出
			sum &= 0xffff;//只保留低两个字节
			sum++;
		}
	}
	return ~(sum & 0xffff);
}
int main() {
	cout << "服务端" << endl;
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);//希望用户使用2.2版本的Socket
	SOCKET S_socket = socket(AF_INET, SOCK_DGRAM, 0);

	//地址类型是IPv4，服务类型是UDP所以是数据报套接字，协议是UDP
	struct sockaddr_in sockAddr;//sockaddr_in用作定义，socketaddr用作函数参数
	memset(&sockAddr, 0, sizeof(sockAddr));  //将结构体清零
	sockAddr.sin_family = AF_INET;//IPv4
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器IP
	sockAddr.sin_port = htons(1234);//端口
	int len = sizeof(sockAddr);
	bind(S_socket, (sockaddr*)&sockAddr, sizeof(sockAddr));
	//服务端需要进行三次握手建连
	//shake(S_socket, (sockaddr*)&sockAddr);

	//-----------------------------三次握手-----------------------------
	cout << "等待第一次握手中..." << endl;
	char buf[100] = { 0 };
	//int len = sizeof(sockAddr);
	recvfrom(S_socket, buf, 8, 0, (sockaddr*)&sockAddr, &len);
	HEADER* recv_head = (HEADER*)buf;
	if (recv_head->flag == SYN && cksum((u_short*)buf, 4) == 0x0000) {//检查标记位和校验和
		cout << "成功进行第一次握手！" << endl;
		cout << "第一次握手的Seq序列号为：" << (int)recv_head->seq_num << endl;
		cout << "第一次握手的Ack序列号为：" << (int)recv_head->ack_num << endl;
	}
	else {
		cout << "ERROR！第一次握手的传输中出现错误！" << endl;
		//goto again;
	}

	cout << endl << "进行第二次握手:" << endl;
	//第二次握手
	head.len = 8;//8个字节
	head.flag = ACK_SYN;
	srand((unsigned)time(NULL));
	head.seq_num = rand() % (MAXBYTE);//产生随机序列号
	head.ack_num = recv_head->seq_num + 1;
	cout << "第二次握手的Seq序列号为：" << (int)head.seq_num << endl;
	cout << "第二次握手的Ack序列号为：" << (int)head.ack_num << endl;
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);

	memcpy(buf, &head, head.len);
	clock_t start;

	while (sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR) {
		cout << "第二次握手send发送失败！重新发送..." << endl;
	}
	cout << endl << "等待第三次握手中....." << endl;
	start = clock();//开启计时

	u_long mode = 1;//非阻塞，否则recv函数会一直等待
	ioctlsocket(S_socket, FIONBIO, &mode);
	char filename[50] = { 0 };
	while (1) {
		if (clock() - start > 2 * TIMEOUT) {
			cout << "超时...重传中..." << endl;
			sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
			cout << endl << "等待第三次握手中....." << endl;
			start = clock();//重启时钟
		}
		else {
			recvfrom(S_socket, buf, 100, 0, (sockaddr*)&sockAddr, (&len));
			recv_head = (HEADER*)buf;
			memcpy(filename, buf + sizeof(HEADER), recv_head->len - sizeof(HEADER));//获取文件名
			//cout << "sum" << cksum((u_short*)buf, recv_head->len / 2 + recv_head->len % 2) << endl;
			if (recv_head->flag == ACK) {
				cout << "成功接收第三次握手内容!" << endl;
				cout << "第三次握手中Ack为" << (int)recv_head->ack_num << endl;
				cout << "第三次握手中Seq为" << (int)recv_head->seq_num << endl;
				cout << endl << "成功建立连接！等待用户传输数据..." << endl;
				cout << "用户传输的文件为:" << filename << endl << "等待接收中..." << endl;
				break;
			}
		}
	}
	mode = 0;
	ioctlsocket(S_socket, FIONBIO, &mode);//恢复阻塞模式
	//-----------------------------三次握手-----------------------------
	// 
	// 
	//-----------------------------传输数据-----------------------------
	char temp[1050] = { 0 };
	FILE* fp = nullptr;
	bool jpg = false;//默认文本
	ofstream fout;
	if (strcmp(&filename[strlen(filename) - 3], "jpg")) {//是文件
		fout.open(filename, ios::app);
	}
	else {
		//fout.open(filename, ios::binary);
		if ((fp = fopen(filename, "wb")) == NULL)//打开文件
		{
			exit(0);
		}
		jpg = true;
	}
	//从buffer中写数据到fp指向的文件中
	//fwrite(buffer, length, 1, fp);
	//关闭文件指针，释放buffer内存

	char fout_buf[1025] = { 0 };
	unsigned char store_seq;
	while (1) {
		memset(temp, 0, 1050);
		recvfrom(S_socket, temp, 1050, 0, (sockaddr*)&sockAddr, (&len));//接收到的数据包放在temp中
		recv_head = (HEADER*)temp;
		if (cksum((u_short*)temp, recv_head->len / 2 + recv_head->len % 2) == 0x0000) {
			if (recv_head->flag == ACK_FIN) {//第一次挥手
				cout << "文件" << filename << "接收完毕" << endl;
				cout << endl << "成功接收到第一次挥手..." << endl;
				cout << "第一次挥手的ack:" << (int)recv_head->ack_num << endl;
				cout << "第一次挥手的seq:" << (int)recv_head->seq_num << endl;
				store_seq = recv_head->seq_num;
				if (jpg)fclose(fp);
				else fout.close();
				break;
			}
			else {//还在接收文件中
				if (jpg) { fwrite(temp + sizeof(HEADER), MAXBUF, 1, fp); }//数据写入文件
				else {
					memcpy(fout_buf, temp + sizeof(HEADER), MAXBUF);
					fout << fout_buf;
				}

				head.len = 8;
				head.flag = ACK;
				head.seq_num = 0;
				if (recv_head->seq_num == 255)
					head.ack_num = 0;
				else {
					head.ack_num = recv_head->seq_num + 1;
				}
				head.ck_sum = 0;
				head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);
				memcpy(buf, &head, sizeof(HEADER));
				sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
			}
		}
	}

	//-----------------------------传输数据-----------------------------
	// 
	//四次挥手
	//memset(buf, 0, sizeof(HEADER) + 1);
	//recvfrom(S_socket, buf, sizeof(HEADER), 0, (sockaddr*)&sockAddr, (&len));//接收到的数据包放在temp中
	//recv_head = (HEADER*)buf;

	head.flag = ACK;//第二次挥手
	head.seq_num = recv_head->ack_num;
	if (recv_head->seq_num == 255)
		head.ack_num = 0;
	else {
		head.ack_num = recv_head->seq_num + 1;
	}
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);
	memcpy(buf, &head, sizeof(HEADER));
	sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
	cout << endl << "第二次挥手的ack:" << (int)recv_head->ack_num << endl;
	cout << "第二次挥手的seq:" << (int)recv_head->seq_num << endl;

	head.flag = ACK_FIN;//第三次挥手
	head.ack_num = store_seq + 1;
	head.seq_num = rand() % (MAXBYTE);
	head.ck_sum = 0;
	head.ck_sum = cksum((u_short*)&head, head.len / 2 + head.len % 2);
	memcpy(buf, &head, sizeof(HEADER));
	sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
	cout << endl << "第三次挥手的ack:" << (int)recv_head->ack_num << endl;
	cout << "第三次挥手的seq:" << (int)recv_head->seq_num << endl;
	start = clock();

	while (1) {
		if (clock() - start > 2 * TIMEOUT) {
			cout << "超时...重传第三次挥手中..." << endl;
			sendto(S_socket, buf, head.len, 0, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
			cout << endl << "等待第四次挥手中....." << endl;
			start = clock();//重启时钟
		}
		else {
			recvfrom(S_socket, buf, 8, 0, (sockaddr*)&sockAddr, (&len));
			recv_head = (HEADER*)buf;
			if (recv_head->flag == ACK) {
				cout << endl << "成功接收第四次挥手内容!" << endl;
				cout << "第四次挥手接收到的ack:" << (int)recv_head->ack_num << endl;
				cout << "第四次挥手接收到的seq:" << (int)recv_head->seq_num << endl;
				break;
			}
		}
	}

	closesocket(S_socket);

	WSACleanup();
}